home *** CD-ROM | disk | FTP | other *** search
- #import "Alexandra.h"
- #import "Article.h"
- #import "ArticleSet.h"
- #import "NewsgroupSet.h"
- #import "Newsgroup.h"
- #import "ArticleViewControl.h"
- #import "Composer.h"
- #import "ColumnMatrix.h"
- #import "ArticleSetMatrix.h"
- #include <assert.h>
- #import <misckit/MiscMailApp.h>
- #import <misckit/MiscString.h>
- #import <misckit/MiscAppDefaults.h>
- #import "response_codes.h"
- #import "plain-subject.h"
- #import "MatrixScroller.h"
- #import "descriptors.h"
-
- @implementation ArticleSet
-
- - init
- {
- currentNewsgroup=nil;
- unselAction=@selector(clear);
- [super init];
- return self;
- }
-
- - awakeFromNib
- {
- char buf1[255];
-
- sprintf(buf1,"SortType %s",[nntpServer serverName]);
- currentSortType=[NXApp defaultIntValue:buf1];
-
- return self;
- }
-
- - free
- {
- [Composer killComposerForServer:nntpServer];
- return [super free];
- }
-
- - loadGroup:(Newsgroup *)aNewsgroup
- {
- int i,j;
- Article *anArticle;
-
- if(aNewsgroup==nil)
- return self;
-
- currentNewsgroup=aNewsgroup;
-
- //get article list
- myMList=[aNewsgroup articleList];
- [myMatrix setMatrixCellList:myMList];
-
- //choose articles to show. Here: all unread
- j=[myMList count];
- for(i=0;i<j;i++){
- anArticle=[myMList objectAt:i];
- if([anArticle isRead])
- [anArticle unsetTag];
- else
- [anArticle setTag];
- }
- [myMatrix setAutodisplay:NO];
- [[myMatrix loadMatrix] scrollUp];
- [[myMatrix setAutodisplay:YES] display];
- [self sync];
-
- return self;
- }
-
- - selectArticle:sender
- {
- int statusCode;
- Article *oldSelection;
-
- [[myMatrix window] makeFirstResponder:myMatrix];
-
- assert(myMList!=NULL);
- oldSelection=currentSelection;
- [self syncAndReturnList:NO];
-
- if(oldSelection==currentSelection)
- return self;
-
- if(numSelCells==1){
- statusCode=[theArticleViewControl loadArticle:currentSelection fromGroup:[[theNewsgroupSet currentSelection] stringValue]];
- if(statusCode!=OK_BODY){
- if(statusCode==-1)
- return self;
- //[myMList removeObject:currentSelection];
- if([currentSelection isRead]==FALSE){
- [[theNewsgroupSet currentSelection] incNumberUnreadArticles:-1];
- [theNewsgroupSet redisplayMatrix];
- }
- [myMatrix perform:@selector(removeInvalidCell:) with:currentSelection afterDelay:0.0 cancelPrevious:YES];
- return self;
- }
- if([currentSelection isRead]==FALSE){
- [currentSelection setRead];
- [[theNewsgroupSet currentSelection] incNumberUnreadArticles:-1];
- [theNewsgroupSet redisplayMatrix];
- }
- }
-
- [myMatrix display];
-
- return self;
- }
-
- - showAll:sender
- {
- if((currentNewsgroup==nil) || (myMList==nil))
- return self;
- [myMList makeObjectsPerform:@selector(setTag)];
- [[myMatrix reloadMatrix] display];
-
- [myMatrix setButtonTitle:"All Articles"];
-
- return self;
- }
-
- - showUnread:sender
- {
- int i,j;
- int oldNumSelCells;
-
- if((currentNewsgroup==NULL) || (myMList==NULL))
- return self;
- j=[myMList count];
- for(i=0;i<j;i++){
- Article* anArticle;
- anArticle=[myMList objectAt:i];
- if([anArticle isRead]==TRUE)
- [anArticle unsetTag];
- else
- [anArticle setTag];
- }
-
- if(currentSelection!=nil)
- [currentSelection setTag];
-
- [[myMatrix reloadMatrix] display];
-
- oldNumSelCells=numSelCells;
- [self sync];
-
- if((oldNumSelCells!=1)&&(numSelCells==1)){
- currentSelection=nil;
- numSelCells=0;
- [self selectArticle:self];
- }
- [myMatrix setButtonTitle:"Unread Articles"];
-
- return self;
- }
-
- - markSelectionReadOrUnread:(BOOL)flag
- {
- /*flag==TRUE <=> Mark unread */
- Article* anArticle;
- int delta;
- List *articleList=nil;
- int i,j;
-
- if(currentNewsgroup==NULL)
- return self;
- articleList=[myMatrix getCurrSelections];
- j=[articleList count];
- delta=0;
- for(i=0;i<j;i++){
- anArticle=[articleList objectAt:i];
- if([anArticle isRead]==flag){
- if(flag==FALSE){
- [anArticle setRead];
- delta-=1;
- }
- else{
- [anArticle setUnread];
- delta+=1;
- }
- }
- }
- if(delta!=0){
- [[theNewsgroupSet currentSelection] incNumberUnreadArticles:delta];
- [theNewsgroupSet redisplayMatrix];
- [myMatrix display];
- }
- [articleList free];
- return self;
- }
-
- - markRead:sender
- {
- [self markSelectionReadOrUnread:FALSE];
- return self;
- }
-
- - markUnread:sender
- {
- [self markSelectionReadOrUnread:TRUE];
- return self;
- }
-
- - followupToSelection:sender
- {
- if(currentSelection!=nil){
- if([self postToSelectedNG:self]!=nil)
- [theComposer followup:self];
- }
- return self;
- }
-
- - postToSelectedNG:sender
- {
- List *selList;
- int i,j;
-
- EM_DURING
-
- selList=[[theNewsgroupSet theMatrix] getCurrSelections];
-
- // warum muss den eine Gruppe ausgewählt sein?
- EM_CONDERROR(([selList count]==0),ECOMPNeedGroup,NULL,NULL);
-
- // See if posting is possible in general
- if([nntpServer canPost]==FALSE)
- EM_ERROR(ECOMPNoPosting,NULL,NULL);
-
- // See if you can post to all groups in list
- j=[selList count];
- for(i=0;i<j;i++){
- char p=[[selList objectAt:i] postable];
-
- if(p=='n')
- EM_ERROR(ECOMPNoPostingToGroup,[[selList objectAt:i] stringValue],NULL);
- }
- // O.K.
- theComposer=[Composer newWindowForServer:nntpServer];
- [theComposer preparePostTo:selList
- selArticle:currentSelection inView:theArticleViewControl];
-
- EM_EMPTYHANDLER
-
- [selList free];
- return self;
- }
-
-
- - clearMatrix
- {
- currentNewsgroup=nil;
- myMList=nil;
- [myMatrix setMatrixCellList:nil];
- [[myMatrix loadMatrix] display];
- [[myMatrix window] flushWindow];
- [self sync];
- return self;
- }
-
- - (const char *)stringValue
- {
- return ptr_to_articlebody;
- }
-
- - forwardArticle:sender
- {
- NXStream *aStream;
- int len,maxlen;
- id subjectStr=[[MiscString init] alloc];
- const char *oldSubjectPtr;
- BOOL is_reply;
- id mailer;
-
- if((currentSelection==nil)||(currentNewsgroup==nil)){
- NXRunAlertPanel("ALEXANDRA","No article selected.",NULL,NULL,NULL);
- return self;
- }
-
- mailer=[MiscMailApp localMailer];
- if(mailer==nil){
- NXRunAlertPanel("ALEXANDRA","Can't reach mail application.",NULL,NULL,NULL);
- return self;
- }
-
- //O.K. first get the articles body
- aStream=NXOpenMemory(NULL,0,NX_WRITEONLY);
- NXPrintf(aStream,"Forwarded Article %s\n",[currentSelection header]->fieldBody[MSG_ID]);
- NXPrintf(aStream,"Newsgroup %s\n",[currentNewsgroup stringValue]);
- NXPrintf(aStream,"From %s\n\n",[currentSelection header]->fieldBody[FROM]);
-
- [theArticleViewControl writeBody:aStream];
- NXGetMemoryBuffer(aStream,&ptr_to_articlebody,&len,&maxlen);
-
- //Compose subject
- oldSubjectPtr=plain_subject((char *)[currentSelection stringValue],&is_reply);
- if(is_reply)
- [subjectStr setStringValue:"Re: "];
- [subjectStr strcat:oldSubjectPtr];
-
- // Open Compose window in mailer
- [mailer sendMailTo:nil subject:currentSelection body:self];
-
- NXCloseMemory(aStream,NX_FREEBUFFER);
- [subjectStr free];
- return self;
- }
-
- - replyByMail:sender
- {
- NXStream *aStream;
- int len,maxlen;
- MiscString *to,*subject;
- char *r;
- BOOL dummy;
- id mailer;
-
- if((currentSelection==nil)||(currentNewsgroup==nil)){
- NXRunAlertPanel("ALEXANDRA","No article selected.",NULL,NULL,NULL);
- return self;
- }
-
- mailer=[MiscMailApp localMailer];
- if(mailer==nil){
- NXRunAlertPanel("ALEXANDRA","Can't reach mail application.",NULL,NULL,NULL);
- return self;
- }
-
- //O.K. first get the articles body
- aStream=NXOpenMemory(NULL,0,NX_WRITEONLY);
- NXPrintf(aStream,"In article %s, you wrote:\n",[currentSelection header]->fieldBody[MSG_ID]);
- [theArticleViewControl writeQuotedText:aStream];
- NXGetMemoryBuffer(aStream,&ptr_to_articlebody,&len,&maxlen);
-
- //Make Subject string
- subject=[[MiscString alloc] init];
- [subject setStringValue:"Re: "];
- [subject strcat:plain_subject([currentSelection header]->fieldBody[SUBJECT], &dummy)];
-
- //Make To
- to=[[MiscString alloc] init];
- r=[currentSelection header]->fieldBody[REPLY_TO];
- if((r==NULL)||(r[0]=='\0'))
- r=[currentSelection header]->fieldBody[FROM];
- [to setStringValue:r];
-
- // Open Compose window in mailer
- [mailer sendMailTo:to subject:subject body:self];
-
- NXCloseMemory(aStream,NX_FREEBUFFER);
- [to free];
- [subject free];
-
- return self;
- }
-
- - cancelArticle:sender
- {
- char *messageID;
- char *mailAddress;
- NXStream *articlestream;
-
- if(currentSelection==nil)
- return nil;
-
- if ((messageID=[currentSelection header]->fieldBody[MSG_ID]) == NULL)
- return nil;
-
- mailAddress = [[FromHeaderController new] validFromAddress];
- if(!mailAddress)
- return self;
-
-
- //Post
- articlestream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
- NXPrintf(articlestream,"Newsgroups: %s\nSubject: cancel\nControl: cancel %s\nFrom: %s\n\ncancel\n",[currentSelection header]->fieldBody[NEWSGROUPS], messageID, mailAddress);
- NXSeek(articlestream, (long)0,NX_FROMSTART);
- [nntpServer postArticle:articlestream];
-
- NXCloseMemory(articlestream,NX_FREEBUFFER);
- free(mailAddress);
- return(self);
- }
-
-
- - setArticleSortType:(int)type
- {
- char buf[255];
- int oldType;
- id selNewsgroup;
-
- sprintf(buf,"SortType %s",[nntpServer serverName]);
- oldType=[NXApp defaultIntValue:buf];
- if(oldType!=type){
- currentSortType=type;
- [NXApp setDefault:buf toInt:type];
- if((selNewsgroup=[theNewsgroupSet currentSelection])!=nil)
- if([selNewsgroup resortIfNeeded:type]){
- [myMatrix reloadMatrix];
- [myMatrix display];
- }
- }
-
- return self;
- }
-
- - sortArticlesByNumber:sender
- {
- [self setArticleSortType:SORT_BY_NUMBER];
- return self;
- }
-
- - sortArticlesByDate:sender
- {
- [self setArticleSortType:SORT_BY_DATE];
- return self;
- }
-
- - sortArticlesBySubject:sender
- {
- [self setArticleSortType:SORT_BY_SUBJECT];
- return self;
- }
-
- - sortArticlesByName:sender
- {
- [self setArticleSortType:SORT_BY_REAL_NAME];
- return self;
- }
-
- - catchUpThreadAt:(int)index
- {
- int i,j;
- id anArticle;
- const char *thread_subject;
- int m=0;
- BOOL dummy;
-
- thread_subject=plain_subject([[myMatrix cellAt:index :0] header]->fieldBody[SUBJECT],&dummy);
- for(i=0,j=[myMList count];i<j;i++){
- anArticle=[myMList objectAt:i];
- if(!strcmp(plain_subject([anArticle header]->fieldBody[SUBJECT],&dummy),thread_subject)){
- if(![anArticle isRead]){
- [anArticle setRead];
- m++;
- }
- }
- }
- if(m>0)
- [[theNewsgroupSet currentSelection] incNumberUnreadArticles:-1*m];
-
- return self;
- }
-
- - skipThreadAndUpOrDown:(int)delta
- {
- int i=[myMatrix selectedRow];
- int a,b,s;
-
- if(i<0){
- NXRunAlertPanel("ALEXANDRA","No article selected.",NULL,NULL,NULL);
- return self;
- }
- [self catchUpThreadAt:i];
- if(delta!=0){
- [myMatrix getNumRows:&a numCols:&b];
-
- s=i+delta;
- while((s>=0) && (s<a)){
- id anArticle=[myMatrix cellAt:s :0];
- if(![anArticle isRead]){
- [myMatrix selectCellAt:s :0];
- [self selectArticle:self];
- [myMatrix scrollCellToVisible:s upperOffset:((delta==-1)? 1.5:0.0) lowerOffset:((delta==1)? 1.5:0.0)];
- break;
- }
- s+=delta;
- }
- }
- [myMatrix display];
- [theNewsgroupSet redisplayMatrix];
-
- return self;
- }
-
- - skipThreadAndUp:sender
- {
- return [self skipThreadAndUpOrDown:-1];
- }
-
- - skipThreadAndDown:sender
- {
- return [self skipThreadAndUpOrDown:1];
- }
-
- - (const char *)stringValueForCellAt:(int)index
- {
- int h=[NXApp defaultIntValue:"findGeneralScope"];
- if((h>=0)&&(h<XOVER_COUNT)){
- char *s=[[myMList objectAt:index] header]->fieldBody[h];
- if(s!=NULL)
- return s;
- }
- return "";
- }
-
- - (BOOL)selectArticleWithMsgid:(const char *)msgid
- {
- int i,j;
-
- for(i=0,j=[myMList count];i<j;i++){
- const char *aMsgid=[[myMList objectAt:i] header]->fieldBody[MSG_ID];
- if(aMsgid && !strcmp(aMsgid,msgid))
- return [self selectArticleWithNumber:[[myMList objectAt:i] number]];
- }
-
- return FALSE;
- }
-
- - (BOOL)selectArticleWithNumber:(long)snumber;
- {
- int i,j;
-
- for(i=0,j=[myMList count];i<j;i++){
- id aCell=[myMList objectAt:i];
- if([aCell number]==snumber){
- if(![aCell isTaged])
- [self showAll:self];
- return [myMatrix selectArticleWithNumber:snumber];
- }
- }
-
- return FALSE;
- }
-
- @end
-